package com.gengzp.rpc.controller;

import com.gengzp.rpc.annotations.RemoteTransactional;
import com.gengzp.rpc.constants.RpcCommonConstants;
import com.gengzp.rpc.core.RemoteTransactionalCoreFunc;
import com.gengzp.rpc.core.RpcCoreFunc;
import com.gengzp.rpc.model.req.RpcRequestReq;
import com.gengzp.rpc.model.resp.RpcRequestResult;
import com.gengzp.rpc.utils.RpcJsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @ClassName RpcProducerController
 * @Description 远程调用框架生产者控制器
 * @Author gengzp
 * @Date 2025/6/1 1:20
 */
@RestController
@RequestMapping(RpcCommonConstants.REMOTE_CALL_PRODUCER_CONTROLLER_URL)
public class RpcProducerController {

    private static final Logger logger = LoggerFactory.getLogger(RpcProducerController.class);

    @Autowired
    private RpcCoreFunc rpcCoreFunc;

    @Autowired
    private RemoteTransactionalCoreFunc remoteTransactionalCoreFunc;

    /**
     * 远程调用生产者接口
     */
    @PostMapping(RpcCommonConstants.REMOTE_CALL_PRODUCER_METHOD_URL)
    public RpcRequestResult doRequest(@RequestBody RpcRequestReq req) {
        logger.info("执行远程调用 -> [{}.{}()] 消费者: [{}]",
                req.getInterfaceClass().getName(), req.getMethodName(), req.getConsumerServiceName());

        try {
            // 获取消费者被调用的bean实例
            Object bean = rpcCoreFunc.getBeanByInterfaceClass(req.getInterfaceClass());
            if (bean == null) {
                return RpcRequestResult.getFailResult("找不到消费者服务实例");
            }

            // 获取方法
            Method method = bean.getClass().getMethod(req.getMethodName(), req.getParameterTypes());
            method.setAccessible(true);

            // 转换参数类型
            Object[] params = new Object[req.getParameterTypes().length];
            for (int i = 0; i < req.getParameterTypes().length; i++) {
                Object arg = req.getArgs()[i];
                params[i] = arg == null ? null : RpcJsonUtils.convertMap2Object(arg, req.getParameterTypes()[i]);
            }

            // 调用指定方法
            Object invoke = method.invoke(bean, params);
            logger.info("远程调用执行结束");

            // 若开启了远程事务, 则保存到redis, 用于后续回滚
            if (Objects.nonNull(method.getAnnotation(RemoteTransactional.class))) {
                remoteTransactionalCoreFunc.saveRemoteTransaction(
                        req.getRequestId(), req.getConsumerServiceName(), req.getInterfaceClass(),
                        req.getMethodName(), req.getParameterTypes(), params);
            }

            return RpcRequestResult.getSuccessResult(invoke);
        } catch (Exception e) {
            logger.error("远程调用异常, 原因描述: ", e);
            return RpcRequestResult.getFailResult(e.getMessage());
        }

    }

}
